﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AForge.Math;

namespace MagicCube_v2_Demo
{
    class FourierTranform
    {
        /********************************************************
       * 用于图片处理的二维快速傅里叶变换
       * imageData：图像序列
       * imageWidth：图像的宽度
       * imageHeight：图像的长度
       * inv：标识是否进行坐标位移变换
       *      true：进行坐标位移变换
       *      false：不进行坐标位移变换
       * 返回变换后的频域数据
       * ******************************************************/
        public static Complex[] fft2(byte[] imageData, int imageWidth, int imageHeight, bool inv)
        {
            int bytes = imageWidth * imageHeight;
            byte[] bmpValues = new byte[bytes];
            Complex[] tempCom1 = new Complex[bytes];

            bmpValues = (byte[])imageData.Clone();

            //赋值：把实数变为复数，即虚部为0
            for (int i = 0; i < bytes; i++)
            {
                if (inv == true)
                {
                    //进行频域坐标位移
                    if ((i / imageWidth + i % imageWidth) % 2 == 0)
                    {
                        tempCom1[i] = new Complex(bmpValues[i], 0);
                    }
                    else
                    {
                        tempCom1[i] = new Complex(-bmpValues[i], 0);
                    }
                }
                else
                {
                    //不进行频域坐标位移
                    tempCom1[i] = new Complex(bmpValues[i], 0);
                }
            }

            //水平方向快速傅里叶变换
            Complex[] tempCom2 = new Complex[imageWidth];
            //Complex[] tempCom3 = new Complex[imageWidth];
            for (int i = 0; i < imageHeight; i++)
            {
                //得到水平方向复数序列
                for (int j = 0; j < imageHeight; j++)
                {
                    tempCom2[j] = tempCom1[i * imageWidth + j];
                }

                //调用一维傅里叶变换
                AForge.Math.FourierTransform.FFT(tempCom2, FourierTransform.Direction.Forward);

                //把结果赋值回去
                for (int j = 0; j < imageWidth; j++)
                {
                    tempCom1[i * imageWidth + j] = tempCom2[j];
                }
            }

            //垂直方向快速傅里叶变换
            Complex[] tempCom4 = new Complex[imageHeight];
            //Complex[] tempCom5 = new Complex[imageHeight];
            for (int i = 0; i < imageHeight; i++)
            {
                for (int j = 0; j < imageHeight; j++)
                {
                    tempCom4[j] = tempCom1[j * imageWidth + i];

                }

                //调用一维傅里叶变换
                AForge.Math.FourierTransform.FFT(tempCom4, FourierTransform.Direction.Forward);

                //把结果赋值回去
                for (int j = 0; j < imageHeight; j++)
                {
                    tempCom1[j * imageHeight + i] = tempCom4[j];
                }

            }

            return tempCom1;

        }
            /*************************************************************************
          * 用于图像处理的二维快速傅里叶逆变换
          * freData：频域数据
          * imageWidth：图像的宽度
          * imageHeight：图像的长度
          * inv：标识是否进行坐标位移变换，要与二维快速傅里叶正变换一致
          *      true：进行坐标位移变换
          *      false：不进行坐标位移变换
          * 返回变换后的空间域数据（即图像数据）
          * **********************************************************************/
        public static byte[] ifft2(Complex[] freData, int imageWidth, int imageHeight, bool inv)
        {
            int bytes = imageWidth * imageHeight;
            byte[] bmpValues = new byte[bytes];
            Complex[] tempCom1 = new Complex[bytes];

            tempCom1 = (Complex[])freData.Clone();

            //水平方向快速傅里叶逆变换
            Complex[] tempCom2 = new Complex[imageWidth];
            Complex[] tempCom3 = new Complex[imageWidth];
            for (int i = 0; i < imageHeight; i++)
            {
                //得到水平方向复数序列
                for (int j = 0; j < imageWidth; j++)
                {
                    tempCom2[j] = tempCom1[i * imageWidth + j];

                }

                //调用一维傅里叶变换
                AForge.Math.FourierTransform.FFT(tempCom2, FourierTransform.Direction.Backward);

                //把结果赋值回去
                for (int j = 0; j < imageWidth; j++)
                {
                    tempCom1[i * imageWidth + j] = tempCom2[j];

                }
            }

            //垂直方向快速傅里叶逆变换
            Complex[] tempCom4 = new Complex[imageHeight];
            //Complex[] tempCom5 = new Complex[imageHeight];
            for (int i = 0; i < imageWidth; i++)
            {
                //得到垂直方向复数序列
                for (int j = 0; j < imageHeight; j++)
                {
                    tempCom4[j] = tempCom1[j * imageWidth + i];
                }

                //调用一维傅里叶逆变换
                AForge.Math.FourierTransform.FFT(tempCom4,
                    FourierTransform.Direction.Backward);

                //把结果赋值回去
                for (int j = 0; j < imageHeight; j++)
                {
                    tempCom1[j * imageHeight + i] = tempCom4[j];
                }
            }

            //赋值：把复数转换成实数，只保留复数的实数部分
            double tempDouble;
            for (int i = 0; i < bytes; i++)
            {
                if (inv == true)
                {
                    //进行坐标位移
                    if ((i / imageWidth + i % imageWidth) % 2 == 0)
                    {
                        tempDouble = tempCom1[i].Re;
                    }
                    else
                    {
                        tempDouble = -tempCom1[i].Re;
                    }
                }
                else
                {
                    //不进行坐标位移
                    tempDouble = tempCom1[i].Re;

                }
                if (tempDouble > 255)
                {
                    bmpValues[i] = 255;
                }
                else
                {
                    if (tempDouble < 0)
                    {
                        bmpValues[i] = 0;
                    }
                    else
                        bmpValues[i] = Convert.ToByte(tempDouble);

                }
            }
            return bmpValues;
        }
    }
}
